﻿namespace HiMap.Carto
{
    using HiMap.Base;
    using HiMap.CoordinateSystem;
    using HiMap.Geometry;
    using System;
    using System.Drawing;
    using System.Reflection;
    using System.Runtime.CompilerServices;
    using System.Text;

    public class Map : HiMapPtrClass
    {
        private bool _EnvelopeUpdate;

        public event EventHandler LayerChanged;

        public Map(string MapName)
        {
            base.m_InPtr = HiMap.Carto.VC.KWG_MAP_CREATE(new StringBuilder(MapName));
            base.m_Used = false;
            this._EnvelopeUpdate = false;
            this.LayerChanged = (EventHandler) Delegate.Combine(this.LayerChanged, new EventHandler(this.OnLayerChanged));
        }

        internal Map(int InPtr, bool Used)
        {
            base.m_InPtr = InPtr;
            base.m_Used = Used;
        }

        public void AddLayer(ILayer Layer)
        {
            switch (Layer.Type)
            {
                case LayerType.FeatureLayer:
                    if (HiMap.Carto.VC.KWG_MAP_ADD_LAYER(base.m_InPtr, Layer.Class.InPtr) >= 0)
                    {
                        Layer.Class.Used = true;
                    }
                    this.LayerChanged(null, null);
                    return;

                case LayerType.RasterLayer:
                    break;

                case LayerType.KRasterLayer:
                {
                    IKRasterLayer layer = (IKRasterLayer) Layer;
                    if (HiMap.Carto.VC.KWG_MAP_ADD_LAYER(base.m_InPtr, layer.InPtr) >= 0)
                    {
                        layer.Used = true;
                    }
                    this.LayerChanged(null, null);
                    break;
                }
                default:
                    return;
            }
        }

        public void Destory()
        {
            if (base.m_InPtr != 0)
            {
                HiMap.Carto.VC.KWG_MAP_DELETE(base.m_InPtr);
                base.m_InPtr = 0;
            }
        }

        public double Distance(IPoint pt1, IPoint pt2)
        {
            return CoordinateSystemClass.Distance(pt1.X, pt1.Y, pt2.X, pt2.Y);
        }

        ~Map()
        {
            if (!base.m_Used && (base.m_InPtr != 0))
            {
                HiMap.Carto.VC.KWG_MAP_DELETE(base.m_InPtr);
            }
        }

        public void FromKmd(string file)
        {
            HiMap.Carto.VC.KWG_MAP_FROMKMD(base.m_InPtr, new StringBuilder(file));
            this.LayerChanged(null, null);
        }

        public ILayer GetLayer(int Index)
        {
            int num = HiMap.Carto.VC.KWG_MAP_GET_LAYER(base.m_InPtr, Index);
            LayerType type = HiMap.Carto.VC.KWG_LAYER_GET_TYPE(num);
            StringBuilder builder = new StringBuilder(0xff);
            HiMap.Carto.VC.KWG_LAYER_GET_NAME(num, builder);
            builder = new StringBuilder(0xff);
            HiMap.Carto.VC.KWG_LAYER_GET_CAPTION(num, builder);
            switch (type)
            {
                case LayerType.FeatureLayer:
                    return new FeatureLayerClass(new FeatureClassClass(num, true));

                case LayerType.KRasterLayer:
                    return new KRasterLayerClass(num, true);
            }
            return null;
        }

        public Point[] MapToScreen(IPoint[] pts)
        {
            Point[] pointArray = new Point[pts.Length];
            for (int i = 0; i < pts.Length; i++)
            {
                pointArray[i] = this.MapToScreen(pts[i].X, pts[i].Y);
            }
            return pointArray;
        }

        public Point MapToScreen(double x, double y)
        {
            int num = HiMap.Carto.VC.KWG_MAP_GET_DISPLAYCONDITION(base.m_InPtr);
            int num2 = 0;
            int num3 = 0;
            HiMap.Carto.VC.KWG_DISPLAYCONDITION_MAP_TO_PIXEL(num, x, y, ref num2, ref num3);
            return new Point(num2, num3);
        }

        public void MoveAtLayer(ILayer Layer, int ToIndex)
        {
            for (int i = 0; i < this.LayerCount; i++)
            {
                if (HiMap.Carto.VC.KWG_MAP_GET_LAYER(base.m_InPtr, i) == Layer.Class.InPtr)
                {
                    HiMap.Carto.VC.KWG_MAP_MOVE_LAYER(base.m_InPtr, i, ToIndex);
                }
            }
            this.LayerChanged(null, null);
        }

        public void MoveAtLayer(int FromIndex, int ToIndex)
        {
            HiMap.Carto.VC.KWG_MAP_MOVE_LAYER(base.m_InPtr, FromIndex, ToIndex);
            this.LayerChanged(null, null);
        }

        private void OnLayerChanged(object sender, EventArgs e)
        {
        }

        public IPoint PointToMapPoint(int x, int y)
        {
            int num = HiMap.Carto.VC.KWG_MAP_GET_DISPLAYCONDITION(base.m_InPtr);
            IPoint point = new PointClass();
            double num2 = 0;
            double num3 = 0;
            HiMap.Carto.VC.KWG_DISPLAYCONDITION_PIXEL_TO_MAP(num, x, y, ref num2, ref num3);
            point.X = num2;
            point.Y = num3;
            return point;
        }

        public void RemoveAtLayer(ILayer Layer)
        {
            for (int i = 0; i < this.LayerCount; i++)
            {
                int num2 = HiMap.Carto.VC.KWG_MAP_GET_LAYER(base.m_InPtr, i);
                if (Layer is IFeatureLayer)
                {
                    if (num2 == Layer.Class.InPtr)
                    {
                        HiMap.Carto.VC.KWG_MAP_REMOVE_LAYER(base.m_InPtr, i);
                    }
                }
                else if (Layer is IKRasterLayer)
                {
                    IKRasterLayer layer = Layer as IKRasterLayer;
                    if (num2 == layer.InPtr)
                    {
                        HiMap.Carto.VC.KWG_MAP_REMOVE_LAYER(base.m_InPtr, i);
                    }
                }
            }
            this.LayerChanged(null, null);
        }

        public void RemoveAtLayer(int Index)
        {
            HiMap.Carto.VC.KWG_MAP_REMOVE_LAYER(base.m_InPtr, Index);
            this.LayerChanged(null, null);
        }

        public void SaveKmd(string file)
        {
            HiMap.Carto.VC.KWG_MAP_SAVEKMD(base.m_InPtr, new StringBuilder(file));
        }

        public void SetFrameBound(int Width, int Height)
        {
            HiMap.Carto.VC.KWG_DISPLAYCONDITION_SET_FRAME(HiMap.Carto.VC.KWG_MAP_GET_DISPLAYCONDITION(base.m_InPtr), Width, Height);
        }

        public void SetMinPixel(int width, int height)
        {
            HiMap.Carto.VC.KWG_DISPLAYCONDITION_SET_SMALLEST_PIXEL(HiMap.Carto.VC.KWG_MAP_GET_DISPLAYCONDITION(base.m_InPtr), width, height);
        }

        public IPoint CenterAt
        {
            get
            {
                int num = HiMap.Carto.VC.KWG_MAP_GET_DISPLAYCONDITION(base.m_InPtr);
                double x = 0;
                double y = 0;
                HiMap.Carto.VC.KWG_DISPLAYCONDITION_GET_CENTER(num, ref x, ref y);
                IPoint point = new PointClass();
                point.X = x;
                point.Y = y;
                return point;
            }
            set
            {
                HiMap.Carto.VC.KWG_DISPLAYCONDITION_SET_CENTER(HiMap.Carto.VC.KWG_MAP_GET_DISPLAYCONDITION(base.m_InPtr), value.X, value.Y);
                this.EnvelopeUpdate = true;
            }
        }

        public ICoordinateSystem CoordinateSystem
        {
            get
            {
                int inPtr = HiMap.Carto.VC.KWG_DISPLAYCONDITION_GET_COORDINATESYSTEM(HiMap.Carto.VC.KWG_MAP_GET_DISPLAYCONDITION(base.m_InPtr));
                if (inPtr == 0)
                {
                    return null;
                }
                return new CoordinateSystemClass(inPtr, true);
            }
            set
            {
                HiMap.Carto.VC.KWG_DISPLAYCONDITION_SET_COORDINATESYSTEM(HiMap.Carto.VC.KWG_MAP_GET_DISPLAYCONDITION(base.m_InPtr), value.InPtr);
            }
        }

        public IEnvelope Envelope
        {
            get
            {
                double minx = 0;
                double miny = 0;
                double maxx = 0;
                double maxy = 0;
                HiMap.Carto.VC.KWG_DISPLAYCONDITION_GET_ENVLOPE(HiMap.Carto.VC.KWG_MAP_GET_DISPLAYCONDITION(base.m_InPtr), ref minx, ref miny, ref maxx, ref maxy);
                IEnvelope envelope = new EnvelopeClass();
                envelope.MinX = minx;
                envelope.MinY = miny;
                envelope.MaxX = maxx;
                envelope.MaxY = maxy;
                return envelope;
            }
            set
            {
                HiMap.Carto.VC.KWG_DISPLAYCONDITION_SET_ENVLOPE(HiMap.Carto.VC.KWG_MAP_GET_DISPLAYCONDITION(base.m_InPtr), value.MinX, value.MinY, value.MaxX, value.MaxY);
                this.EnvelopeUpdate = true;
            }
        }

        public bool EnvelopeUpdate
        {
            get
            {
                return this._EnvelopeUpdate;
            }
            set
            {
                this._EnvelopeUpdate = value;
            }
        }

        public IEnvelope FullEnvelope
        {
            get
            {
                double minx = 0;
                double maxx = 0;
                double miny = 0;
                double maxy = 0;
                HiMap.Carto.VC.KWG_DISPLAYCONDITION_GET_FULLENVLOPE(HiMap.Carto.VC.KWG_MAP_GET_DISPLAYCONDITION(base.m_InPtr), ref minx, ref miny, ref maxx, ref maxy);
                IEnvelope envelope = new EnvelopeClass();
                envelope.MinX = minx;
                envelope.MinY = miny;
                envelope.MaxX = maxx;
                envelope.MaxY = maxy;
                return envelope;
            }
        }

        public int Height
        {
            get
            {
                return HiMap.Carto.VC.KWG_DISPLAYCONDITION_GET_FRAME_HEIGHT(HiMap.Carto.VC.KWG_MAP_GET_DISPLAYCONDITION(base.m_InPtr));
            }
        }

        public double HeightMeter
        {
            get
            {
                int num = HiMap.Carto.VC.KWG_MAP_GET_DISPLAYCONDITION(base.m_InPtr);
                double width = 0;
                double height = 0;
                HiMap.Carto.VC.KWG_DISPLAYCONDITION_GET_FRAME_METER(num, ref width, ref height);
                return height;
            }
        }

        public ILayer this[int Index]
        {
            get
            {
                int num = HiMap.Carto.VC.KWG_MAP_GET_LAYER(base.m_InPtr, Index);
                if (HiMap.Carto.VC.KWG_LAYER_GET_TYPE(num) == LayerType.FeatureLayer)
                {
                    return new FeatureLayerClass(new FeatureClassClass(num, true));
                }
                return null;
            }
        }

        public bool LabelDodge
        {
            get
            {
                return HiMap.Carto.VC.KWG_DISPLAYCONDITION_GET_LABEL_DODGE(HiMap.Carto.VC.KWG_MAP_GET_DISPLAYCONDITION(base.m_InPtr));
            }
            set
            {
                int num = HiMap.Carto.VC.KWG_MAP_GET_DISPLAYCONDITION(base.m_InPtr);
                if (value)
                {
                    HiMap.Carto.VC.KWG_DISPLAYCONDITION_GET_LABEL_OPENDODGE(num);
                }
                else
                {
                    HiMap.Carto.VC.KWG_DISPLAYCONDITION_GET_LABEL_CLOSEDODGE(num);
                }
            }
        }

        public int LayerCount
        {
            get
            {
                return HiMap.Carto.VC.KWG_MAP_GET_LAYERCOUNT(base.m_InPtr);
            }
        }

        public int MapAngle
        {
            get
            {
                return HiMap.Carto.VC.KWG_DISPLAYCONDITION_GET_ANGLE(HiMap.Carto.VC.KWG_MAP_GET_DISPLAYCONDITION(base.m_InPtr));
            }
            set
            {
                HiMap.Carto.VC.KWG_DISPLAYCONDITION_SET_ANGLE(HiMap.Carto.VC.KWG_MAP_GET_DISPLAYCONDITION(base.m_InPtr), value);
            }
        }

        public string MapName
        {
            get
            {
                StringBuilder builder = new StringBuilder(0xff);
                HiMap.Carto.VC.KWG_MAP_GET_NAME(base.m_InPtr, builder);
                return builder.ToString();
            }
        }

        public double MapScale
        {
            get
            {
                int num = HiMap.Carto.VC.KWG_MAP_GET_DISPLAYCONDITION(base.m_InPtr);
                double scale = 0;
                HiMap.Carto.VC.KWG_DISPLAYCONDITION_GET_SCALE(num, ref scale);
                return scale;
            }
            set
            {
                HiMap.Carto.VC.KWG_DISPLAYCONDITION_SET_SCALE(HiMap.Carto.VC.KWG_MAP_GET_DISPLAYCONDITION(base.m_InPtr), value);
                this.EnvelopeUpdate = true;
            }
        }

        public int MinPixelHeight
        {
            get
            {
                return HiMap.Carto.VC.KWG_DISPLAYCONDITION_GET_SMALLEST_HEIGHT_PIXEL(HiMap.Carto.VC.KWG_MAP_GET_DISPLAYCONDITION(base.m_InPtr));
            }
        }

        public int MinPixelWidth
        {
            get
            {
                return HiMap.Carto.VC.KWG_DISPLAYCONDITION_GET_SMALLEST_WIDTH_PIXEL(HiMap.Carto.VC.KWG_MAP_GET_DISPLAYCONDITION(base.m_InPtr));
            }
        }

        public IProjection Pro
        {
            get
            {
                int inPtr = HiMap.Carto.VC.KWG_DISPLAYCONDITION_GET_PROJECTION(HiMap.Carto.VC.KWG_MAP_GET_DISPLAYCONDITION(base.m_InPtr));
                if (inPtr == 0)
                {
                    return null;
                }
                return new Projection_GaussClass(inPtr, true);
            }
            set
            {
                HiMap.Carto.VC.KWG_DISPLAYCONDITION_SET_PROJECTION(HiMap.Carto.VC.KWG_MAP_GET_DISPLAYCONDITION(base.m_InPtr), value.InPtr);
            }
        }

        public double ScaleRuler
        {
            get
            {
                return ((this.Envelope.MaxX - this.Envelope.MinX) / this.WidthMeter);
            }
        }

        public int Width
        {
            get
            {
                return HiMap.Carto.VC.KWG_DISPLAYCONDITION_GET_FRAME_WIDTH(HiMap.Carto.VC.KWG_MAP_GET_DISPLAYCONDITION(base.m_InPtr));
            }
        }

        public double WidthMeter
        {
            get
            {
                int num = HiMap.Carto.VC.KWG_MAP_GET_DISPLAYCONDITION(base.m_InPtr);
                double width = 0;
                double height = 0;
                HiMap.Carto.VC.KWG_DISPLAYCONDITION_GET_FRAME_METER(num, ref width, ref height);
                return width;
            }
        }
    }
}

